

#include <iostream>
#include <string>
#include <tuple>

template <typename... Strings>
class lazy_string_concat_helper;

template <typename LastString, typename... Strings>
class lazy_string_concat_helper<LastString,
                                Strings...> {
private:
    // Stores the copy of the original string
    LastString data;

    // Stores the structure that contains other strings
    lazy_string_concat_helper<Strings...> tail;

    public:
        lazy_string_concat_helper(
            LastString data,
            lazy_string_concat_helper<Strings...> tail)
        : data(data)
        , tail(tail)
    {
    }
    // Calculates the size of all strings combined
    int size() const
    {
        int size =  data.size() + tail.size();
        std::cout  << size <<std::endl;
        return size;
    }

    // The structure stores strings in reverse order: the data
    // member variable contains the string that comes last,
    // so it needs to go to the end of the buffer.
        template<typename It>
        void save(It end) const
        {
            const auto begin = end - data.size();
        std::copy(data.cbegin(), data.cend(),
                  begin);
        tail.save(begin);
        std::cout  << data.size() << "," << tail.size() <<std::endl;
        }

        // When you want to convert the expression definition into a real string,
    // allocate enough memory and start copying the strings into it.
    operator std::string() const
    {
        std::string result(size(), '\0');
        save(result.end());
        return result;
    }

        lazy_string_concat_helper<std::string,
                                    LastString,
                                    Strings...>
        operator+(const std::string& other) const
        {
            return lazy_string_concat_helper
                    <std::string,LastString,Strings...>(
                        other,
                        *this
                    );
        }
};
template <>
class lazy_string_concat_helper<> {
public:
    lazy_string_concat_helper()
    {
    }

    int size() const
    {
        return 0;
    }

    template <typename It>
    void save(It) const
    {
    }

    lazy_string_concat_helper<std::string>
    operator+(const std::string& other) const
    {
          std::cout << other <<std::endl;
        return lazy_string_concat_helper<std::string>(
                other,
                *this
            );
    }
};
lazy_string_concat_helper<> lazy_concat;

int main(int argc, char* argv[])
{
    std::string name = "Jane123456";
    std::string surname = "Smith";
    const std::string fullname = 
        lazy_concat + surname + "," + name;
    std::cout << fullname <<std::endl;
    return 0;
}